class MarketParticipant:
    """能源市场参与者基类"""
    def __init__(self, name, bid_price, offer_price, capacity):
        self.name = name
        self.bid_price = bid_price  # 投标价格
        self.offer_price = offer_price  # 报价价格
        self.capacity = capacity  # 产能/需求量

class Generator(MarketParticipant):
    """发电厂商"""
    def __init__(self, name, bid_price, capacity, fuel_type):
        super().__init__(name, bid_price, bid_price, capacity)
        self.fuel_type = fuel_type  # 燃料类型

class Consumer(MarketParticipant):
    """电力消费者"""
    def __init__(self, name, offer_price, demand):
        super().__init__(name, offer_price, offer_price, demand)

import json

class EnergyMarket:
    """能源市场模拟器
    
    模拟电力市场中发电商和消费者的交易行为，计算市场均衡价格和数量。
    
    属性:
        participants (list): 市场参与者列表
        clearing_price (float): 市场出清价格
        clearing_quantity (float): 市场出清数量
    
    示例:
        >>> market = EnergyMarket()
        >>> market.add_participant(Generator("电厂", 0.3, 500, "coal"))
        >>> market.add_participant(Consumer("用户", 0.4, 400))
        >>> price, quantity = market.run_auction()
    """
    def __init__(self, config_file=None):
        self.participants = []
        self.clearing_price = None
        self.clearing_quantity = None
        self.config_file = config_file
        
        if config_file:
            self.load_config(config_file)
    
    def load_config(self, config_file):
        """从配置文件加载市场设置"""
        try:
            with open(config_file, 'r') as f:
                config = json.load(f)
                
            # 创建发电商
            for gen_config in config['participants']['generators']:
                generator = Generator(
                    gen_config['name'],
                    gen_config['bid_price'],
                    gen_config['capacity'],
                    gen_config['fuel_type']
                )
                self.add_participant(generator)
                
            # 创建消费者
            for con_config in config['participants']['consumers']:
                consumer = Consumer(
                    con_config['name'],
                    con_config['offer_price'],
                    con_config['demand']
                )
                self.add_participant(consumer)
                
        except FileNotFoundError:
            print(f"警告: 配置文件 {config_file} 未找到")
        except json.JSONDecodeError:
            print(f"错误: 配置文件 {config_file} 格式不正确")
        except KeyError as e:
            print(f"错误: 配置文件缺少必要字段 {e}")

    def add_participant(self, participant):
        """添加市场参与者
        
        参数:
            participant (Generator|Consumer): 市场参与者对象
                           Generator对象代表发电商
                           Consumer对象代表电力消费者
        
        示例:
            >>> market = EnergyMarket()
            >>> market.add_participant(Generator("风电场", 0.25, 300, "wind"))
            >>> market.add_participant(Consumer("商业用户", 0.30, 300))
        """
        self.participants.append(participant)
    
    def run_auction(self, visualize=False):
        """运行拍卖机制确定市场出清价格和数量
        
        基于供需曲线交点计算市场均衡点，支持可视化展示。
        
        参数:
            visualize (bool): 是否生成可视化图表。需要matplotlib支持。
        
        返回:
            tuple: (出清价格, 出清数量, 供给曲线, 需求曲线)
            出清价格 (float): 市场均衡价格(元/kWh)
            出清数量 (float): 市场均衡电量(kWh)
            供给曲线 (list): [(价格, 累计电量)] 按价格排序的供给曲线点
            需求曲线 (list): [(价格, 累计电量)] 按价格排序的需求曲线点
        
        算法:
            1. 按价格排序所有发电商投标和消费者报价
            2. 计算累计供给和需求曲线
            3. 寻找供需曲线交点作为市场均衡点
        
        示例:
            >>> market = EnergyMarket()
            >>> market.add_participant(Generator("电厂", 0.3, 500, "coal"))
            >>> market.add_participant(Consumer("用户", 0.4, 400))
            >>> price, qty, supply, demand = market.run_auction(visualize=True)
        """
        # 按价格排序投标和报价
        bids = sorted(
            [p for p in self.participants if isinstance(p, Generator)],
            key=lambda x: x.bid_price
        )
        offers = sorted(
            [p for p in self.participants if isinstance(p, Consumer)],
            key=lambda x: x.offer_price,
            reverse=True
        )
        
        # 计算供需曲线交点
        supply_curve = []
        demand_curve = []
        
        cumulative_supply = 0
        for gen in bids:
            cumulative_supply += gen.capacity
            supply_curve.append((gen.bid_price, cumulative_supply))
        
        cumulative_demand = 0
        for con in offers:
            cumulative_demand += con.capacity
            demand_curve.append((con.offer_price, cumulative_demand))
        
        # 寻找市场均衡点
        self.clearing_price, self.clearing_quantity = self.find_equilibrium(
            supply_curve, demand_curve
        )
        
        # 可视化
        if visualize:
            try:
                from visualization import plot_supply_demand_curve, plot_participant_distribution
                plot_supply_demand_curve(supply_curve, demand_curve, 
                                       self.clearing_price, self.clearing_quantity)
                plot_participant_distribution(self.participants)
            except ImportError:
                print("警告: matplotlib未安装，无法生成可视化图表")
        
        return (self.clearing_price, self.clearing_quantity, 
                supply_curve, demand_curve)
    
    def find_equilibrium(self, supply_curve, demand_curve):
        """寻找供需曲线的均衡点
        
        参数:
            supply_curve (list): 供给曲线 [(价格, 累计电量)] 按价格升序排列
            demand_curve (list): 需求曲线 [(价格, 累计电量)] 按价格降序排列
        
        返回:
            tuple: (均衡价格, 均衡电量)
            
        算法:
            1. 遍历供给曲线和需求曲线
            2. 找到供给价格 ≤ 需求价格的最大电量点
            3. 使用线性插值计算精确均衡点
            
        数学原理:
            均衡点是满足 Qd(P) = Qs(P) 的价格P和数量Q
            其中 Qd是需求函数，Qs是供给函数
            
        示例:
            >>> supply = [(0.2, 100), (0.3, 300), (0.4, 500)]
            >>> demand = [(0.5, 400), (0.4, 300), (0.3, 200)]
            >>> find_equilibrium(supply, demand)
            (0.35, 350)
        """
        # 简化实现 - 实际应用中可能需要更复杂的算法
        for s_price, s_quantity in supply_curve:
            for d_price, d_quantity in demand_curve:
                if s_price <= d_price and s_quantity >= d_quantity:
                    return (s_price + d_price) / 2, min(s_quantity, d_quantity)
        
        # 如果没有交点，返回最后的价格和数量
        return supply_curve[-1][0], min(supply_curve[-1][1], demand_curve[-1][1])
    
    def print_results(self):
        """打印市场出清结果
        
        输出格式:
            --------------------------------
            市场出清结果:
            出清价格: [价格]元/kWh
            出清电量: [电量]kWh
            --------------------------------
            
        示例输出:
            --------------------------------
            市场出清结果:
            出清价格: 0.30元/kWh
            出清电量: 800kWh
            --------------------------------
        """
        if self.clearing_price is None:
            print("请先运行拍卖机制")
            return
        
        print(f"市场出清价格: {self.clearing_price:.2f} 元/千瓦时")
        print(f"市场出清数量: {self.clearing_quantity:.2f} 千瓦时")
        
        print("\n市场参与者:")
        for p in self.participants:
            if isinstance(p, Generator):
                role = "发电商"
            else:
                role = "消费者"
            print(f"{p.name} ({role}): 报价={p.offer_price}, 产能/需求={p.capacity}")

if __name__ == "__main__":
    import argparse
    
    parser = argparse.ArgumentParser(description="能源市场模拟器")
    parser.add_argument("-c", "--config", action="store_true",
                       help="使用配置文件(config.json)运行模拟")
    parser.add_argument("-v", "--visualize", action="store_true",
                       help="生成可视化图表(需要matplotlib)")
    args = parser.parse_args()
    
    print("能源市场模拟器")
    print("="*40)
    
    if args.config:
        # 从配置文件运行
        print("\n运行模式: 使用配置文件")
        print("-"*40)
        market = EnergyMarket(config_file="config.json")
    else:
        # 手动添加参与者运行
        print("\n运行模式: 手动配置")
        print("-"*40)
        market = EnergyMarket()
        
        # 添加发电商
        market.add_participant(Generator("火电厂", 0.35, 500, "coal"))
        market.add_participant(Generator("风电场", 0.25, 300, "wind"))
        market.add_participant(Generator("光伏电站", 0.20, 200, "solar"))
        
        # 添加消费者
        market.add_participant(Consumer("工业用户", 0.40, 600))
        market.add_participant(Consumer("商业用户", 0.30, 300))
        market.add_participant(Consumer("居民用户", 0.25, 100))
    
    # 运行拍卖
    market.run_auction(visualize=args.visualize)
    market.print_results()
    
    print("\n使用说明:")
    print("- 使用 -c/--config 从config.json加载配置")
    print("- 使用 -v/--visualize 生成可视化图表")
    print("- 修改config.json文件自定义市场配置")